﻿using Application_Core.Arbeitsplan_Component.Access_Layer;
using Application_Core.Bauteil_Component.Access_Layer;
using Application_Core.Bestellung_Component.Access_Layer;
using Application_Core.Kunde_Component.Access_Layer;
using Application_Core.Lieferung_Component.Access_Layer;
using Application_Core.Rechnung_Component.Access_Layer;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using Utility.Persistence_Service;
using Utility.Persistence_Service.Implementations;
using Utility.RabbitMQ_Service;
using Utility.RabbitMQ_Service.Implementations;
using Utility.RabbitMQ_Service.MessageTypes;

namespace Manufacturing_Planning_System_Server
{
    internal class RPCListener
    {
        private readonly String systemName;

        private RPCListener(String systemName) { }

        public static RPCListener NewRPCListener(String systemName)
        {
            return new RPCListener(systemName);
        }

        public void StartListener()
        {
            UnitOfWorkFactory unitOfWorkFactory = UnitOfWorkFactoryImpl.CreateUnitOfWork(false);
            using (UnitOfWork unit = unitOfWorkFactory.NewUnitOfWork())
            {
                KundeService kundeService = new KundeComponentFacade(unit);
                BestellungService bestellungService = new BestellungComponentFacade(unit);
                RechnungService rechnungService = new RechnungComponentFacade(unit);
                LieferungService lieferungService = new LieferungComponentFacade(unit);
                BauteilService bauteilService = new BauteilComponentFacade(unit);
                ArbeitsplanService arbeitsplanService = new ArbeitsplanComponentFacade(unit);

                using (RabbitMQService service = RabbitMQServiceImpl.CreateRabbitMQService())
                {
                    try
                    {
                        while (true)
                        {
                            Object result = null;
                            String concurrencyId = null;

                            using (RabbitMQQueue<MethodRequestMessage> queue = service.NewRabbitMQQueue<MethodRequestMessage>("dispatcher.requests"))
                            {
                                MethodRequestMessage request = queue.ReceiveRPC();
                                concurrencyId = queue.GetCorrelationId();

                                Type objectType = (from asm in AppDomain.CurrentDomain.GetAssemblies()
                                                   from type in asm.GetTypes()
                                                   where type.IsClass && type.Name == request.ReturnTypeName
                                                   select type).Single();

                                Object instance = Activator.CreateInstance(objectType, new Object[] { unit });

                                var methodInfo = objectType.GetMethod(request.MethodName);
                                result = methodInfo.Invoke(instance, request.Args);
                            }

                            using (RabbitMQQueue<MethodResponseMessage> queue = service.NewRabbitMQQueue<MethodResponseMessage>("dispatcher.responses"))
                            {
                                queue.SetCorrelationId(concurrencyId);

                                MethodResponseMessage response = new MethodResponseMessage()
                                {
                                    SystemName = this.systemName,
                                    ReturnedType = result.GetType(),
                                    ReturnedValue = result
                                };

                                queue.Send(response);
                            }
                        }
                    }
                    catch (ThreadInterruptedException)
                    {
                        Console.WriteLine("StartAndStop-Listener wurde beendet.");
                    }
                }
            }
        }
    }
}
